/**
 * @file        lcd.h
 * @brief       LCD驱动头文件
 * @details     本驱动支持多种TFT LCD控制器的初始化和显示操作
 *              支持的控制器：ILI9341/ST7789/NT35310/ST7796/NT35510/ILI9806/SSD1963
 *              硬件接口：使用GPIO模拟16位并行接口
 *              分辨率支持：240×320、320×480、480×800等多种分辨率
 */

#ifndef __LCD_H
#define __LCD_H

#include "stdlib.h"
#include "./SYSTEM/SYS/sys.h"

/* ------------------------------------------- LCD日志配置 -------------------------------------------- */

/* LCD模块日志总开关 - 设置为0可一键关闭所有LCD日志 */
#define LCD_LOG_ENABLE              1

/* LCD模块日志标签 */
#define LCD_LOG_TAG                 "LCD"

#include "elog.h"

/* LCD日志级别控制宏 - 可通过修改这些宏来控制不同级别日志的开启/关闭 */
#define LCD_LOG_ASSERT_ENABLE       1       /* 断言日志开关 */
#define LCD_LOG_ERROR_ENABLE        1       /* 错误日志开关 */
#define LCD_LOG_WARN_ENABLE         1       /* 警告日志开关 */
#define LCD_LOG_INFO_ENABLE         1       /* 信息日志开关 */
#define LCD_LOG_DEBUG_ENABLE        1       /* 调试日志开关 */
#define LCD_LOG_VERBOSE_ENABLE      1       /* 详细日志开关 */

/* LCD日志输出宏定义 */
#if (LCD_LOG_ENABLE && LCD_LOG_ASSERT_ENABLE)
    #define LCD_LOG_A(...)          elog_assert(LCD_LOG_TAG, __VA_ARGS__)
#else
    #define LCD_LOG_A(...)
#endif

#if (LCD_LOG_ENABLE && LCD_LOG_ERROR_ENABLE)
    #define LCD_LOG_E(...)          elog_error(LCD_LOG_TAG, __VA_ARGS__)
#else
    #define LCD_LOG_E(...)
#endif

#if (LCD_LOG_ENABLE && LCD_LOG_WARN_ENABLE)
    #define LCD_LOG_W(...)          elog_warn(LCD_LOG_TAG, __VA_ARGS__)
#else
    #define LCD_LOG_W(...)
#endif

#if (LCD_LOG_ENABLE && LCD_LOG_INFO_ENABLE)
    #define LCD_LOG_I(...)          elog_info(LCD_LOG_TAG, __VA_ARGS__)
#else
    #define LCD_LOG_I(...)
#endif

#if (LCD_LOG_ENABLE && LCD_LOG_DEBUG_ENABLE)
    #define LCD_LOG_D(...)          elog_debug(LCD_LOG_TAG, __VA_ARGS__)
#else
    #define LCD_LOG_D(...)
#endif

#if (LCD_LOG_ENABLE && LCD_LOG_VERBOSE_ENABLE)
    #define LCD_LOG_V(...)          elog_verbose(LCD_LOG_TAG, __VA_ARGS__)
#else
    #define LCD_LOG_V(...)
#endif

/* ----------------------------------------------------- LCD引脚定义 ---------------------------------------------- */

/**
 * @brief LCD硬件接口说明
 * @note  本驱动使用GPIO模拟16位并行接口，不使用FSMC控制器
 *        
 *        硬件连接说明：
 *        - LCD_CS:  片选信号（Chip Select）
 *        - LCD_WR:  写使能信号（Write Enable）
 *        - LCD_RD:  读使能信号（Read Enable）
 *        - LCD_RS:  寄存器选择信号（Register Select，也称DC/A0）
 *        - LCD_BL:  背光控制信号（Backlight）
 *        - LCD_DATA: 16位数据总线（D0~D15），使用GPIOB的16个引脚
 *        
 *        移植说明：
 *        移植时需要修改以下引脚定义和lcd_init()函数中的数据引脚配置
 */

/* LCD控制引脚定义 - 根据实际硬件连接修改 */

/* RESET 和系统复位脚共用 所以这里不用定义 RESET引脚 */
//#define LCD_RST_GPIO_PORT               GPIOx
//#define LCD_RST_GPIO_PIN                SYS_GPIO_PINx
//#define LCD_RST_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOx_CLK_ENABLE(); }while(0)   /* 所在IO口时钟使能 */

/* LCD_WR引脚定义 */
#define LCD_WR_GPIO_PORT                GPIOC
#define LCD_WR_GPIO_PIN                 GPIO_PIN_7
#define LCD_WR_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)     /* 所在IO口时钟使能 */

/* LCD_RD引脚定义 */
#define LCD_RD_GPIO_PORT                GPIOC
#define LCD_RD_GPIO_PIN                 GPIO_PIN_6
#define LCD_RD_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)     /* 所在IO口时钟使能 */

/* LCD_BL引脚定义 */
#define LCD_BL_GPIO_PORT                GPIOC
#define LCD_BL_GPIO_PIN                 GPIO_PIN_10
#define LCD_BL_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)     /* 背光所在IO口时钟使能 */

/* LCD_CS引脚定义 */
#define LCD_CS_GPIO_PORT                GPIOC
#define LCD_CS_GPIO_PIN                 GPIO_PIN_9
#define LCD_CS_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)     /* 所在IO口时钟使能 */

/* LCD_RS引脚定义 */
#define LCD_RS_GPIO_PORT                GPIOC
#define LCD_RS_GPIO_PIN                 GPIO_PIN_8
#define LCD_RS_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)     /* 所在IO口时钟使能 */

/* LCD_DATA引脚定义 */
#define LCD_DATA_GPIO_PORT              GPIOB
#define LCD_DATA_GPIO_PIN               GPIO_PIN_All                                    /* 16个IO都用到 */
#define LCD_DATA_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)     /* 所在IO口时钟使能 */

/* -------------------------------------------------- LCD控制定义 ------------------------------------------------- */

/**
 * @brief LCD端口控制宏定义
 * @note  使用直接操作寄存器的方式控制GPIO引脚，提高屏幕刷新率
 *        相比HAL库函数调用，直接寄存器操作可显著提升显示性能
 *        
 *        控制原理：
 *        - 使用BSRR寄存器实现原子操作，避免读-改-写过程
 *        - BSRR[15:0]：置位操作，BSRR[31:16]：复位操作
 *        - 公式：BSRR = PIN << (16 * (!x)) 实现高低电平控制
 */
#define LCD_BL(x)       LCD_BL_GPIO_PORT->BSRR = LCD_BL_GPIO_PIN << (16 * (!x))         /* 设置BL引脚 */

#define LCD_WR(x)       LCD_WR_GPIO_PORT->BSRR = LCD_WR_GPIO_PIN << (16 * (!x))         /* 设置WR引脚 */
#define LCD_RD(x)       LCD_RD_GPIO_PORT->BSRR = LCD_RD_GPIO_PIN << (16 * (!x))         /* 设置RD引脚 */
#define LCD_CS(x)       LCD_CS_GPIO_PORT->BSRR = LCD_CS_GPIO_PIN << (16 * (!x))         /* 设置CS引脚 */
#define LCD_RS(x)       LCD_RS_GPIO_PORT->BSRR = LCD_RS_GPIO_PIN << (16 * (!x))         /* 设置RS引脚 */

#define LCD_DATA_OUT(x) LCD_DATA_GPIO_PORT->ODR = x                                     /* 写B0~B15引脚 */
#define LCD_DATA_IN     LCD_DATA_GPIO_PORT->IDR                                         /* 读B0~B15引脚 */

/* -------------------------------------------- LCD数据结构定义 --------------------------------------------------- */

/**
 * @brief LCD设备参数结构体
 * @note  管理LCD控制器的重要参数，支持多种控制器的统一管理
 */
typedef struct
{
    uint16_t width;     /* LCD 宽度 */
    uint16_t height;    /* LCD 高度 */
    uint16_t id;        /* LCD ID */
    uint8_t dir;        /* 横屏还是竖屏控制：0，竖屏；1，横屏。 */
    uint16_t wramcmd;   /* 开始写gram指令 */
    uint16_t setxcmd;   /* 设置x坐标指令 */
    uint16_t setycmd;   /* 设置y坐标指令 */
} _lcd_dev;

/* -------------------------------------------- LCD扫描方向和颜色定义 ----------------------------------------------- */

/**
 * @brief LCD扫描方向定义
 * @note  控制LCD内部GRAM的读写方向，影响显示内容的方向
 *        L2R: Left to Right (从左到右)
 *        R2L: Right to Left (从右到左)
 *        U2D: Up to Down (从上到下)
 *        D2U: Down to Up (从下到上)
 */
#define L2R_U2D         0           /* 从左到右,从上到下 */
#define L2R_D2U         1           /* 从左到右,从下到上 */
#define R2L_U2D         2           /* 从右到左,从上到下 */
#define R2L_D2U         3           /* 从右到左,从下到上 */

#define U2D_L2R         4           /* 从上到下,从左到右 */
#define U2D_R2L         5           /* 从上到下,从右到左 */
#define D2U_L2R         6           /* 从下到上,从左到右 */
#define D2U_R2L         7           /* 从下到上,从右到左 */

#define DFT_SCAN_DIR    L2R_U2D     /* 默认的扫描方向 */

/**
 * @brief 常用颜色定义（RGB565格式）
 * @note  颜色格式：RGB565，即R(5位) + G(6位) + B(5位) = 16位
 *        颜色值计算公式：Color = (R<<11) | (G<<5) | B
 */
#define WHITE           0xFFFF      /* 白色 */
#define BLACK           0x0000      /* 黑色 */
#define RED             0xF800      /* 红色 */
#define GREEN           0x07E0      /* 绿色 */
#define BLUE            0x001F      /* 蓝色 */ 
#define MAGENTA         0xF81F      /* 品红色/紫红色 = BLUE + RED */
#define YELLOW          0xFFE0      /* 黄色 = GREEN + RED */
#define CYAN            0x07FF      /* 青色 = GREEN + BLUE */  

/**
 * @brief 扩展颜色定义（RGB565格式）
 * @note  提供更多颜色选择，用于丰富的界面设计
 */
#define BROWN           0xBC40      /* 棕色 */
#define BRRED           0xFC07      /* 棕红色 */
#define GRAY            0x8430      /* 灰色 */ 
#define DARKBLUE        0x01CF      /* 深蓝色 */
#define LIGHTBLUE       0x7D7C      /* 浅蓝色 */ 
#define GRAYBLUE        0x5458      /* 灰蓝色 */ 
#define LIGHTGREEN      0x841F      /* 浅绿色 */  
#define LGRAY           0xC618      /* 浅灰色(PANNEL),窗体背景色 */ 
#define LGRAYBLUE       0xA651      /* 浅灰蓝色(中间层颜色) */ 
#define LBBLUE          0x2B12      /* 浅棕蓝色(选择条目的反色) */ 

/* -------------------------------------------- SSD1963参数定义(一般不用改) ----------------------------------------- */

/**
 * @brief SSD1963控制器显示参数配置
 * @note  这些参数针对SSD1963控制器的大屏幕显示进行优化
 *        一般情况下不需要修改，除非使用特殊规格的屏幕
 *        
 *        参数说明：
 *        - 分辨率：800×480像素
 *        - 时序参数：根据屏幕规格书配置
 *        - 自动计算：HT、HPS、VT、VPS参数由宏自动计算
 */

/* SSD1963显示分辨率配置 */ 
#define SSD_HOR_RESOLUTION      800     /* LCD水平分辨率 */ 
#define SSD_VER_RESOLUTION      480     /* LCD垂直分辨率 */ 

/* SSD1963时序参数配置 */ 
#define SSD_HOR_PULSE_WIDTH     1       /* 水平脉宽 */ 
#define SSD_HOR_BACK_PORCH      46      /* 水平前廊 */ 
#define SSD_HOR_FRONT_PORCH     210     /* 水平后廊 */ 

#define SSD_VER_PULSE_WIDTH     1       /* 垂直脉宽 */ 
#define SSD_VER_BACK_PORCH      23      /* 垂直前廊 */ 
#define SSD_VER_FRONT_PORCH     22      /* 垂直前廊 */ 

/* SSD1963自动计算参数（请勿手动修改） */ 
#define SSD_HT          (SSD_HOR_RESOLUTION + SSD_HOR_BACK_PORCH + SSD_HOR_FRONT_PORCH)
#define SSD_HPS         (SSD_HOR_BACK_PORCH)
#define SSD_VT          (SSD_VER_RESOLUTION + SSD_VER_BACK_PORCH + SSD_VER_FRONT_PORCH)
#define SSD_VPS         (SSD_VER_BACK_PORCH)

/* -------------------------------------------------- 全局变量声明 ------------------------------------------------- */

/* LCD参数 */
extern _lcd_dev lcddev; /* 管理LCD重要参数 */

/* LCD的画笔颜色和背景色 */
extern uint32_t  g_point_color;     /* 画笔颜色 */
extern uint32_t  g_back_color;      /* 背景颜色 */

/* -------------------------------------------------- 函数声明 ----------------------------------------------------- */

/* 基础操作函数 */
void lcd_wr_data(volatile uint16_t data);            /* LCD写数据 */
void lcd_wr_regno(volatile uint16_t regno);          /* LCD写寄存器编号/地址 */
void lcd_write_reg(uint16_t regno, uint16_t data);   /* LCD写寄存器的值 */

/* 初始化和控制函数 */
void lcd_init(void);                        /* 初始化LCD */ 
void lcd_display_on(void);                  /* 开显示 */ 
void lcd_display_off(void);                 /* 关显示 */
void lcd_scan_dir(uint8_t dir);             /* 设置屏扫描方向 */ 
void lcd_display_dir(uint8_t dir);          /* 设置屏幕显示方向 */ 
void lcd_set_direction(uint8_t direction);  /* 设置屏幕显示方向(竖屏正向/横屏正向/竖屏反向/横屏反向) */
void lcd_ssd_backlight_set(uint8_t pwm);    /* SSD1963 背光控制 */ 

/* 基本绘图函数 */
void lcd_write_ram_prepare(void);                           /* 准备写GRAM */ 
void lcd_set_cursor(uint16_t x, uint16_t y);                /* 设置光标 */ 
uint32_t lcd_read_point(uint16_t x, uint16_t y);            /* 读点(32位颜色,兼容LTDC) */
void lcd_draw_point(uint16_t x, uint16_t y, uint32_t color);/* 画点(32位颜色,兼容LTDC) */

/* 图形绘制函数 */
void lcd_clear(uint16_t color);                                                             /* LCD清屏 */
void lcd_fill_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color);                   /* 填充实心圆 */
void lcd_draw_circle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color);                  /* 画圆 */
void lcd_draw_hline(uint16_t x, uint16_t y, uint16_t len, uint16_t color);                  /* 画水平线 */
void lcd_set_window(uint16_t sx, uint16_t sy, uint16_t width, uint16_t height);             /* 设置窗口 */
void lcd_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t color);          /* 纯色填充矩形(32位颜色,兼容LTDC) */
void lcd_color_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color);   /* 彩色填充矩形 */
void lcd_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);     /* 画直线 */
void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);/* 画矩形 */

/* 字符显示函数 */
void lcd_show_char(uint16_t x, uint16_t y, char chr, uint8_t size, uint8_t mode, uint16_t color);                       /* 显示一个字符 */
void lcd_show_num(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint16_t color);                     /* 显示数字 */
void lcd_show_xnum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint8_t mode, uint16_t color);      /* 扩展显示数字 */
void lcd_show_string(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t size, char *p, uint16_t color);   /* 显示字符串 */

#endif
